鐵人賽 React javascript nodejs
![]()
鐵人賽第18天,今天我們要來優化我們的ToDoApp,讓它更好用,提升它的好用度。
Remove button
send後,消除輸入的文字Message.js,讓每個獨立的代辦事項,有自己的元件。bullet前置符號,我們將原本的<div>改為<li>
// Message.js
import React from "react";
export default function Message(props) {
  return (
    <li>
      {props.msg} <button>{"Delete"}</button>
    </li>
  );
}
<li>來顯示,當然也要針對ToDoList.js中的<div>改為<ul>囉// ToDoList.js
import React, { useContext } from "react";
import { ContextStore } from "./ToDoApp";
import Message from "./Message";  //<-- 引入Message
export default function ToDoList() {
  const { appReducer } = useContext(ContextStore);
  const toDoList = appReducer[0];
  const result = toDoList.map((e, idx) => (
    <Message key={`cmd-${idx}`} msg={e} />   //<-- 改用Message component來顯示
  ));
  return (<ul>{result}</ul>)    //<--改為<ul>去顯示
}
bullet符號,旁邊還有Remove提供訊息的刪除
toDoList是Array的型態吧,我們利用Day10-章節介紹的解構賦值,拷貝一份到新的 Array// reducer.js
export default function reducers(toDoList, action) {
  let newToDoList = [...toDoList];
  switch (action.type) {
    case "ADD":
      newToDoList.push(action.newEvent); 
      break;
    
    // 新增Delete的部分
    case "DEL":
      newToDoList = newToDoList.filter(msg=>msg!==action.delMsg)  // 利用filter,移除toDoList之中的delMsg
      // console.log("Remove: "+action.delMsg); //<--利用console.log(), 可以快速測試是否與事件觸發連結上
      break;
    default:
      console.log("toDoList", toDoList);
      break;
  }
  return newToDoList;
}
Message.js,我們將delete button的onClick事件與Reducer的DEL做個連結,讓訊息可以順利的從Array中移除// Message.js
import React, {useContext} from "react";
import { ContextStore } from "./ToDoApp";
// 新增onClick delete事件,並與`Reducer`的`DEL`做個連結
function handleDelEvent(delMsg, dispatch) {
  return (e) => dispatch({ type: "DEL", delMsg: delMsg });
}
export default function Message(props) {
  const {appReducer} = useContext(ContextStore);
  const dispatch = appReducer[1];
  return (
    <li>
      {props.msg} <button onClick={handleDelEvent(props.msg, dispatch)}>{"Delete"}</button>
    </li>
  );
}
按下刪除前
按下刪除之後,順利的刪除囉
- 開啟
 input.js- 第一步:還記得
 input中的onChane會存取msg吧,而input value剛好也是存取input框中的文字,讓這個變數跟著msg就可以實現囉![]()
- 第二步:我們傳遞
 setMsg到handleAddClickfunc,
// input.js
import React, { useContext, useState } from "react";
import { ContextStore } from "./ToDoApp";
function handleAddClick(newMsg, dispatch, setMsg) {
  const anEvent = { type: "ADD", newEvent: newMsg };
  return (e) => {
    setMsg("");      //<-- 給空的字串,完成清除input的動作
    dispatch(anEvent);
  };
}
export default function Input() {
  const [msg, setMsg] = useState("");
  const { appReducer } = useContext(ContextStore);
  const dispatch = appReducer[1];
  return (
    <div>
      <input
        style={{ width: "150px" }}
        onChange={(e) => setMsg(e.target.value)}
        value={msg}
    ></input>
      <button onClick={handleAddClick(msg, dispatch, setMsg)}>{"Send"}</button>
    </div>
  );
}
Chrome browser內建的localStore來暫存toDoList,並在每次存取時更新它,就不用擔心重新整理後,代辦事項消失囉。// ToDoApp.js
import React, { useReducer, createContext } from "react";
import reducers from "./reducers";
import ToDoList from "./ToDoList";
import Input from "./Input";
export const ContextStore = createContext();
export default function ToDoApp() {
  const appReducer = useReducer(
    reducers,
    localStorage.getItem("toDoList")
      ? localStorage.getItem("toDoList").split(",") //<-- true: 對字串做split, 可直接得到array, ex: 'aaa,bbb,ccc'=>['aaa', 'bbb', 'ccc']
      : [] //<-- false: 給一個空的陣列即可
  ); 
  return (
    <ContextStore.Provider value={{ appReducer: appReducer }}>
      <div>
        <h2 style={{ borderBottom: "1.5px black solid" }}>To Do List</h2>
        <Input />
        <ToDoList />
      </div>
    </ContextStore.Provider>
  );
}
reducers.js中,隨時更新toDoList到localStorage中// reducers
export default function reducers(toDoList, action) {
  let newToDoList = [...toDoList];
  switch (action.type) {
    case "ADD":
      newToDoList.push(action.newEvent); 
      break;
    
    // 新增Delete的部分
    case "DEL":
      newToDoList = newToDoList.filter(msg=>msg!==action.delMsg)  // 利用filter,移除toDoList之中的delMsg
      console.log("Remove: "+action.delMsg);
      break;
    default:
      console.log("toDoList", toDoList);
      break;
  }
  localStorage.setItem('toDoList', newToDoList) //<-- 讓browser能夠暫存這筆資料,重新整理就不用擔心資料遺失囉
  return newToDoList;
}
Google Chrome inspector的console看看,輸入localStorage.toDoList,不錯,確實有存進去喔!
Message一個獨一無二的值,並在Reducer DEL進行判斷處理,這部分就交給各位練習看看!ToDoApp,提升app的使用者體驗。app,過程中,我們將所學的複習運用,相信各位對React都更加熟練了。超棒的你~繼續Rock!!